{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 异或问题表(学习目标)\n",
    ">\n",
    "|   A   |   B   | XOR |\n",
    "|:-----:|:-----:|:---:|\n",
    "|   0   |   0   |  0  |\n",
    "|   0   |   1   |  1  |\n",
    "|   1   |   0   |  1  |\n",
    "|   1   |   1   |  0  |"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "训练前的权重1\n",
      "[[0.09762701 0.43037873]\n",
      " [0.20552675 0.08976637]]\n",
      "训练前的权重2\n",
      "[[-0.16595599]\n",
      " [ 0.44064899]]\n",
      "训练后的权重1\n",
      "[[0.94064478 8.03615726]\n",
      " [0.94064494 8.03627251]]\n",
      "训练后的权重2\n",
      "[[-38.4568068 ]\n",
      " [ 30.67419499]]\n",
      "样本：[0 0]\t预测值为：[0.02001008]\t真实值为：0.0\n",
      "样本：[1 0]\t预测值为：[0.952799]\t真实值为：1.0\n",
      "样本：[0 1]\t预测值为：[0.952799]\t真实值为：1.0\n",
      "样本：[1 1]\t预测值为：[0.0631473]\t真实值为：0.0\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "\n",
    "class NeuralNetwork():\n",
    "    def __init__(self):\n",
    "        np.random.seed(0)\n",
    "        self.weights1 = 2 * np.random.random((2, 2)) - 1\n",
    "        np.random.seed(1)\n",
    "        self.weights2 = 2 * np.random.random((2, 1)) - 1\n",
    "\n",
    "    # sigmoid激活函数\n",
    "    def sigmoid(self, x):\n",
    "        return 1 / (1 + np.exp(-x))\n",
    "\n",
    "    # sigmoid函数的导函数\n",
    "    def dsigmoid(self, x):\n",
    "        return x * (1 - x)\n",
    "\n",
    "    # 前向传播\n",
    "    def activation(self, inputs,weights):\n",
    "        return self.sigmoid(np.dot(inputs, weights))\n",
    "\n",
    "    # 神经网络\n",
    "    def train(self, training_set_inputs, training_set_outputs, number_of_training,lr=0.2):\n",
    "        for iteration in range(number_of_training):\n",
    "            # 训练集导入神经网络\n",
    "            in_hide = np.dot(training_set_inputs, self.weights1)    \n",
    "            out_hide = self.sigmoid(in_hide)    \n",
    "            in_output = np.dot(out_hide, self.weights2)    \n",
    "            output = self.sigmoid(in_output)    \n",
    "            # derivative to the weights of the second layer\n",
    "            d_weight2 = np.dot(out_hide.T, (training_set_outputs - output)*self.dsigmoid(output))   \n",
    "            d_weight1 = np.dot(training_set_inputs.T, np.dot((training_set_outputs - output)*self.dsigmoid(output),self.weights2.T)*self.dsigmoid(out_hide))   \n",
    "            self.weights2 += lr*d_weight2\n",
    "            self.weights1 += lr*d_weight1\n",
    "\n",
    "            \n",
    "nn = NeuralNetwork()\n",
    "print(\"训练前的权重1\")\n",
    "print(nn.weights1)\n",
    "print(\"训练前的权重2\")\n",
    "print(nn.weights2)\n",
    "\n",
    "# 训练集，四个样本\n",
    "X = np.array([ [0, 0],\n",
    "            [1, 0],\n",
    "            [0, 1],\n",
    "            [1, 1]])\n",
    "y = np.array([[0, 1, 1, 0]]).T\n",
    "\n",
    "# 训练神经网络，学习率默认0.2\n",
    "num=100000\n",
    "nn.train(X, y, num)\n",
    "\n",
    "print(\"训练后的权重1\")\n",
    "print(nn.weights1)\n",
    "print(\"训练后的权重2\")\n",
    "print(nn.weights2)\n",
    "# 测试\n",
    "for i,x in enumerate(X):\n",
    "    y_pred=nn.activation(nn.activation(x,nn.weights1),nn.weights2)\n",
    "    print(f\"样本：{x}\\t预测值为：{y_pred}\\t真实值为：{float(y[i])}\")\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}